package pw.hais.utils;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

/**
 * 压缩、解压工具
 * Created by hais1992 on 2016/1/27/027.
 */
public class ZipUtil {
    private static final int BUFF_SIZE = 1024 * 1024; // 1M Byte
    private static boolean stopZipFlag;         //是否停止


    /**
     * 压缩文件 或 文件夹
     *
     * @param fileUrl     压缩的目录 或文件
     * @param saveZipFile 存放的地方
     * @param listenter
     */
    public static void zipPath(String fileUrl, String saveZipFile, OnListenter listenter) {
        try {
            ZipOutputStream zipout = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(saveZipFile), BUFF_SIZE));
            File file = new File(fileUrl);
            if (file.isDirectory()) {
                File[] files = file.listFiles();
                for (File resFile : files) {
                    if(stopZipFlag)zipFile(resFile, zipout, resFile.getName(), listenter);
                }
            } else {
                if(stopZipFlag)zipFile(file, zipout,file.getName() , listenter);
            }
            zipout.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压缩一个文件
     *
     * @param zipFile 压缩文件
     * @param folderPath 解压缩的目标目录
     */
    public static void upZipFile(File zipFile, String folderPath) {
        File desDir = new File(folderPath);
        if (!desDir.exists()) {
            desDir.mkdirs();
        }
        ZipFile zf = null;
        try {
            zf = new ZipFile(zipFile);
            for (Enumeration<?> entries = zf.entries(); entries.hasMoreElements();) {
                ZipEntry entry = ((ZipEntry)entries.nextElement());
                InputStream in = zf.getInputStream(entry);
                String str = folderPath + File.separator + entry.getName();
//                str = new String(str.getBytes("8859_1"), "GB2312");
                File desFile = new File(str);
                if (!desFile.exists()) {
                    File fileParentDir = desFile.getParentFile();
                    if (!fileParentDir.exists()) {
                        fileParentDir.mkdirs();
                    }
                    desFile.createNewFile();
                }
                OutputStream out = new FileOutputStream(desFile);
                byte buffer[] = new byte[BUFF_SIZE];
                int realLength;
                while ((realLength = in.read(buffer)) > 0) {
                    out.write(buffer, 0, realLength);
                }
                in.close();
                out.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }


    /**
     * 获得压缩文件内文件列表
     *
     * @param zipFile 压缩文件
     * @return 压缩文件内文件名称
     */
    public static ArrayList<String> getZipFileNames(File zipFile) {
        ArrayList<String> entryNames = new ArrayList<String>();
        Enumeration<?> entries = null;
        try {
            entries = getEntriesEnumeration(zipFile);
            while (entries.hasMoreElements()) {
                ZipEntry entry = ((ZipEntry)entries.nextElement());
                entryNames.add(new String(getEntryName(entry).getBytes("GB2312"), "8859_1"));
            }
            return entryNames;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获得压缩文件内压缩文件对象以取得其属性
     *
     * @param zipFile 压缩文件
     * @return 返回一个压缩文件列表
     */
    private static Enumeration<?> getEntriesEnumeration(File zipFile) {
        ZipFile zf = null;
        try {
            zf = new ZipFile(zipFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zf.entries();

    }

    /**
     * 取得压缩文件对象的名称
     *
     * @param entry 压缩文件对象
     * @return 压缩文件对象的名称
     */
    private static String getEntryName(ZipEntry entry)  {
        try {
            return new String(entry.getName().getBytes("GB2312"), "8859_1");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }


    /** 压缩文件 */
    private static void zipFile(File resFile, ZipOutputStream zipout, String baseFileURL, OnListenter listenter) {
        try {
            if(stopZipFlag)return;
            if (resFile.isDirectory()) {
                baseFileURL = new String((baseFileURL + "/").getBytes("8859_1"), "GB2312");
                File[] files = resFile.listFiles();
                for (File file : files) {
                    if(stopZipFlag)zipFile(file, zipout, baseFileURL + file.getName(), listenter);
                }
                return;
            }

            byte buffer[] = new byte[BUFF_SIZE];
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(resFile), BUFF_SIZE);
            zipout.putNextEntry(new ZipEntry(baseFileURL));

            int realLength;
            while ((realLength = in.read(buffer)) != -1) {
                zipout.write(buffer, 0, realLength);
            }
            in.close();
            zipout.flush();
            zipout.closeEntry();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }












    public static void stopZip(boolean stopZipFlag) {
        ZipUtil.stopZipFlag = stopZipFlag;
    }

    interface OnListenter {
        void onProgress(int progress);
    }
}
